using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Rensoft.CRM.Client.Editors;
using Rensoft.CRM.Client.ItemViews;
using Rensoft.CRM.Client.HostingAPI;
using Rensoft.CRM.Client.AccountsAPI;

namespace Rensoft.CRM.Client
{
    public partial class Program : Form
    {
        private bool connected;
        private BaseView focusedItemView;
        private Dictionary<string, BaseView> itemViewTable;

        protected delegate void UpdateConnectionStatusInvoker(string status);

        public Program()
        {
            InitializeComponent();
            Text = AssemblyInfo.Product;
            itemViewTable = new Dictionary<string, BaseView>();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            TreeNode accountsNode = menuTreeView.Nodes.Add("Accounts", "Accounts", "Account.ico", "Account.ico");
            TreeNode clientsNode = accountsNode.Nodes.Add("Clients", "Clients", "Client.ico", "Client.ico");
            TreeNode suppliersNode = accountsNode.Nodes.Add("Suppliers", "Suppliers", "Supplier.ico", "Supplier.ico");
            TreeNode servicesNode = menuTreeView.Nodes.Add("Services", "Services", "Service.ico", "Service.ico");
            TreeNode websitesNode = servicesNode.Nodes.Add("Websites", "Websites", "Website.ico", "Website.ico");
            TreeNode domainsNode = servicesNode.Nodes.Add("Domains", "Domains", "Domain.ico", "Domain.ico");
            TreeNode mailboxesNode = servicesNode.Nodes.Add("Mailboxes", "Mailboxes", "Mailbox.ico", "Mailbox.ico");
            TreeNode invoiceNode = menuTreeView.Nodes.Add("Invoices", "Invoices", "Invoices.ico", "Invoices.ico");
            TreeNode salesInvoiceNode = invoiceNode.Nodes.Add("SalesInvoices", "Sales", "SalesInvoices.ico", "SalesInvoices.ico");
            TreeNode paymentsNode = menuTreeView.Nodes.Add("Payments", "Payments", "Invoices.ico", "Invoices.ico");
            TreeNode creditsNode = menuTreeView.Nodes.Add("Credits", "Credits", "Invoices.ico", "Invoices.ico");

            menuTreeView.ExpandAll();
            menuTreeView.SelectedNode = clientsNode;
        }

        public bool ConfirmConnection(
            System.Web.Services.Protocols.SoapHttpClientProtocol service,
            MethodInvoker testMethod)
        {
            if (!connected)
            {
                // Only show on initial connection.
                itemCountLabel.Visible = false;
                connectionStatusLabel.Visible = true;
                connectionStatusLabel.Text = "Connecting...";
            }

            try
            {
                // Causes exception on connection failure.
                testMethod.Invoke();

                connected = true;
                connectionStatusLabel.Visible = false;
                itemCountLabel.Visible = true;
            }
            catch (Exception exception)
            {
                connected = false;

                UpdateConnectionStatusInvoker update =
                    new UpdateConnectionStatusInvoker(updateConnectionStatus);
                Invoke(update, "Disconnected");

                string error = "\r\n" + exception.Message;
                if (exception.InnerException != null)
                {
                    error += "\r\n" + exception.InnerException.Message;
                }

                DialogResult result = MessageBox.Show(
                    "Unable to establish connection to '" + service.Url + "'.\r\n" + error,
                    "Connection Failed", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);

                switch (result)
                {
                    case DialogResult.Cancel:
                        return false;

                    case DialogResult.Retry:
                        ConfirmConnection(service, testMethod);
                        break;
                }
            }

            return true;
        }

        private void updateConnectionStatus(string status)
        {
            connectionStatusLabel.Text = status;
        }

        public void LoadEditorAsync(BaseEditor editor)
        {
            editor.LoadComplete += new EventHandler(OnEditorLoadComplete);
            editor.SaveComplete += new EventHandler(OnEditorSaveComplete);
            editor.LoadAsync();
        }

        protected void OnEditorLoadComplete(object sender, EventArgs e)
        {
            ((BaseEditor)sender).Show();
        }

        protected void OnEditorSaveComplete(object sender, EventArgs e)
        {
            focusedItemView.UpdateItems();
        }

        private void accountToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadEditorAsync(new AccountEditor(this));
        }

        private void websiteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadEditorAsync(new WebsiteEditor(this));
        }

        private void mailboxToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadEditorAsync(new MailboxEditor(this));
        }

        private void domainToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadEditorAsync(new DomainEditor(this));
        }

        private void clientInvoiceToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadEditorAsync(new InvoiceSalesEditor(this));
        }

        private void supplierInvoiceToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void menuTreeView_AfterSelect(object sender, TreeViewEventArgs e)
        {
            string itemViewKey = e.Node.Name;

            if (!itemViewTable.ContainsKey(itemViewKey))
            {
                switch (itemViewKey)
                {
                    case "Clients":
                        focusedItemView = new ClientView(this);
                        break;

                    case "Suppliers":
                        focusedItemView = new SupplierView(this);
                        break;

                    case "Websites":
                        focusedItemView = new WebsiteView(this);
                        break;

                    case "Domains":
                        focusedItemView = new DomainView(this);
                        break;

                    case "Mailboxes":
                        focusedItemView = new MailboxView(this);
                        break;

                    case "SalesInvoices":
                        focusedItemView = new InvoiceSalesView(this);
                        break;

                    case "Payments":
                        focusedItemView = new PaymentView(this);
                        break;

                    case "Credits":
                        focusedItemView = new CreditView(this);
                        break;

                    case "Invoices":
                    case "Services":
                    case "Accounts":
                        // Intentionally do nothing.
                        return;

                    default:
                        throw new NotSupportedException(
                            "View with key '" + itemViewKey + "' is not supported.");
                }

                itemViewTable[itemViewKey] = focusedItemView;
                focusedItemView.Dock = DockStyle.Fill;
                focusedItemView.ItemCountChanged += new EventHandler(itemView_ItemCountChanged);

                splitContainer1.Panel2.Controls.Add(focusedItemView);
            }
            else
            {
                focusedItemView = itemViewTable[itemViewKey];
                focusedItemView.Show();
            }

            foreach (Control control in splitContainer1.Panel2.Controls)
            {
                if (control.Name != focusedItemView.Name)
                {
                    control.Hide();
                }
            }

            // Change window title to reflect displayed view.
            Text = focusedItemView.Title + " - " + AssemblyInfo.Title;

            newToolStripButton.Image = focusedItemView.NewButtonImage;

            focusedItemView.UpdateItems();
        }

        void itemView_ItemCountChanged(object sender, EventArgs e)
        {
            BaseView itemView = (BaseView)sender;
            if (itemView.Visible)
            {
                string itemsText = ((itemView.ItemCount == 1) ? " Item" : " Items");
                itemCountLabel.Text = itemView.ItemCount + itemsText;
            }
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Program());
        }

        private void refreshToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (focusedItemView.CanUpdate)
            {
                focusedItemView.UpdateItems();
            }
        }

        private void viewToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
        {
            refreshToolStripMenuItem.Enabled = false;
            if ((focusedItemView != null) && focusedItemView.CanUpdate)
            {
                refreshToolStripMenuItem.Enabled = true;
            }
        }

        private void newToolStripButton_ButtonClick(object sender, EventArgs e)
        {
            LoadEditorAsync(focusedItemView.GetEditor());
        }

        private void Program_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Control && (e.KeyCode == Keys.N))
            {
                e.Handled = true;
                LoadEditorAsync(focusedItemView.GetEditor());
            }
        }

        private void newHiddenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadEditorAsync(focusedItemView.GetEditor());
        }

        private void paymentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadEditorAsync(new PaymentEditor(this));
        }

        private void creditToolStripMenuItem_Click(object sender, EventArgs e)
        {
            LoadEditorAsync(new CreditEditor(this));
        }
    }
}